package com.lhm.config;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.lhm.dao.UserDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.*;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.security.web.authentication.logout.LogoutHandler;
import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;


//WebSecurityConfigurerAdapter  Web 安全配置模板
@Configuration
@EnableWebSecurity
public class MyConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    UserDetailsService UserDetailsService;

    @Autowired
    PasswordEncoder ps;
    @Autowired
    ObjectMapper objectMapper;

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(UserDetailsService);
    }

    @Override
    public void configure(WebSecurity web) throws Exception {
        //ignoring 忽略 ，放屁
        //解决静态资源被拦截的问题;
        web.ignoring().antMatchers("/css/**");
        web.ignoring().antMatchers("/js/**");
        web.ignoring().antMatchers("/img/**");
        web.ignoring().antMatchers("/api/fore/**");

        //解决服务注册 url 被拦截的问题;
        web.ignoring().antMatchers("/resources/**");
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
         http.formLogin().loginPage("/api/fore/hello")
                .loginProcessingUrl("/dologin")
                .successHandler(new AuthenticationSuccessHandler() {            //登陆成功后
                    @Override
                    public void onAuthenticationSuccess(HttpServletRequest req,
                                                        HttpServletResponse resp,
                                                        Authentication auth)    //当前用户登陆信息
                            throws IOException, ServletException {
                        System.out.println("登录成功 ....." + auth);
                        Object principal = auth.getPrincipal();
                        System.out.println("登录成功 .Authorities...." + auth.getAuthorities());

                        Collection<? extends GrantedAuthority> authorities = auth.getAuthorities();
                        System.out.println("登录成功 .Authorities...." + auth.getAuthorities());


                                resp.setContentType("application/json;charset=utf-8");
                                PrintWriter out = resp.getWriter();
                                resp.setStatus(200);
                                Map<String, Object> map = new HashMap<>();
                                map.put("status", 200);
                                map.put("code", 0);
                                map.put("msg", "登录成功");
                                for (GrantedAuthority authority : authorities) {
                                    System.out.println("authority.getAuthority()=" + authority.getAuthority());
                                    if (authority.getAuthority().contains("G")) {
                                        map.put("action", "/api/fore/login");
                                    }
                                }

               out.write(objectMapper.writeValueAsString(map));
               out.flush();
               out.close();
                    }


})
                .failureHandler(new AuthenticationFailureHandler() {         //登陆失败后
                    @Override
                    public void onAuthenticationFailure(HttpServletRequest req,
                                                        HttpServletResponse resp,
                                                        AuthenticationException e)  //获取登陆失败原因
                            throws IOException {
                                System.out.println("登录失败");
                                PrintWriter out=resp.getWriter();
                                Map<String, Object> map = new HashMap<>();
                                map.put("status", 401);
                                map.put("code", -1);
                                if (e instanceof LockedException) {
                                    map.put("msg", "账户被锁定，登录失败!");
                                } else if (e instanceof BadCredentialsException) {
                                    map.put("msg", "账户名或密码输入错误，登录失败!");
                                } else if (e instanceof DisabledException) {
                                    map.put("msg", "账户被禁用，登录失败!");
                                } else if (e instanceof AccountExpiredException) {
                                    map.put("msg", "账户已过期，登录失败!");
                                } else if (e instanceof CredentialsExpiredException) {
                                    map.put("msg", "密码已过期，登录失败!");
                                } else {
                                    map.put("msg", "登录失败!");
                                }
                                out.write(objectMapper.writeValueAsString("/api/fore/login"));
                                out.flush();
                                out.close();
                    }
                })
                .permitAll()
                .and()
                .logout()                   //开启注销登陆
                .logoutUrl("/logout")        //注销登陆请求url
                .clearAuthentication(true)    //清除身份信息
                .invalidateHttpSession(true)   //session失效
                .addLogoutHandler(new LogoutHandler() { //注销处理
                    @Override
                    public void logout(HttpServletRequest req,
                                       HttpServletResponse resp,
                                       Authentication auth) {

                    }
                })
                .logoutSuccessHandler(new LogoutSuccessHandler(){     //注销成功处理
                    @Override
                    public void onLogoutSuccess(HttpServletRequest req,
                                                HttpServletResponse resp,
                                                Authentication auth)
                            throws IOException {
                        resp.sendRedirect("/login");              //跳转到自定义登陆页面
                    }
                })
                .and()
                .authorizeRequests()
                .antMatchers("/api/fore/**").permitAll()
                 .antMatchers("/api/blog/**").permitAll()
                .anyRequest().authenticated() //需要登录才能访问
        .and()
        .csrf()
        .disable();

    }
}
